#pragma once

#include <iostream>
#include <string>
#include <cstdint>
#include <thread>

#include <sys/wait.h>
#include <unistd.h>

#include "Socket.hpp"
#include "thread_pool.hpp"

using namespace std;
using namespace SocketModule;

class TcpServer
{
    static const uint16_t default_port = 0;

    void HandleRequeat(SockPtr sock) // 处理请求
    {
        while (true)
        {
            // 读取请求
            string in;
            int n = sock->Recv(in);
            if (n > 0) // 读取成功
            {
                LOG(LogLevel::DEBUG) << "client# " << in;

                // 处理请求--echo
                string out = "server# ";
                out += in;

                sock->Send(out);
            }
            else if (n == 0) // 连接断开
            {
                LOG(LogLevel::DEBUG) << "客户端退出";
                sock->Close();
                break;
            }
            else
            {
                LOG(LogLevel::ERROR) << "recv error";
            }
        }
    }

public:
    TcpServer(uint16_t port = default_port)
        : _port(port),
          _listensocket(make_shared<TcpSocket>(port)),
          _isrunning(false)
    {
    }
    void InitServer()
    {
        // 创建lisentsocket
        _listensocket->BuildSocket(SockType::LISTEN_SOCK);
    }
    void Start()
    {

        _mutex.lock();          // 保护_isrunning
        if (_isrunning == true) // 不允许重复启动
        {
            return;
        }
        _isrunning = true;

        while (_isrunning)
        {
            _mutex.unlock();
            // 主线程负责获取新连接
            uint32_t client_ip;
            uint16_t client_port;
            SockPtr sock = _listensocket->Accept(client_ip, client_port);
            if (sock == nullptr) // 获取新连接失败
            {
                continue;
            }
            // 连接管理--线程池版本
            // 创建线程池
            ThreadPool<function<void()>> *t = ThreadPool<function<void()>>::GetInstance();
            t->Start(); // 启动线程池
            t->PushTask([this, sock]()
                        { this->HandleRequeat(sock); });

            // 连接管理--多线程版本
            /*thread t([this,sock]()
            {
                this->HandleRequeat(sock);
            });
            t.detach();//线程分离*/

            //---------------------------//

            // 连接管理--多进程版本
            /*int n = fork();
            if (n == 0) // 子进程
            {
                // 创建孙子进程，并让孙子进程变成孤儿进程
                // 这样就不需要主动等待回收了
                if (fork() > 0)
                {
                    // 子进程退出
                    exit(0);
                }

                // 孙子进程去处理请求
                HandleRequeat(sock);
                // 孙子进程退出
                exit(0);
            }
            // 回收退出的子进程
            sock->Close(); // 父进程关闭fd，防止fd泄漏

            int r = waitpid(n, nullptr, 0);
            if (r < 0)
            {
                LOG(LogLevel::ERROR) << "waitpid error";
            }*/
        }
    }
    void Stop()
    {
        lock_guard<mutex> lock(_mutex); // 保护_isrunning
        _isrunning = false;
    }
    ~TcpServer()
    {
        _listensocket->Close();
    }

private:
    uint16_t _port;
    SockPtr _listensocket;
    bool _isrunning;
    mutex _mutex;
};